<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
			html,body {
				margin: 0;
				padding: 0;
			}
			.canvas-container {
				display: none;
				border: 1px solid #ddd;
			}
			
			.canvas-container2 {
				display: block;
				border: 1px solid #ddd;
			}
		</style>
	</head>
	<body>
		<!-- 
			0.input file  => 读取图片
			1.canvas画布 => 自适应 => 图片的大小就是画布的大小
			2.绘制图片 => drawImage
			3.蒙层 => 黑色半透明的层
			4.截图的矩形 => 在蒙层上方鼠标移动的范围内进行图片再绘制
			5.获取当前图片的数据
			6.放入另一个canvas
		 -->
		<div>
			<input type="file" id="oImageFile" accept="image/*">
		</div>
		<div class="canvas-container">
			<canvas id="canvas"></canvas>
		</div>
		<div class="canvas-container2">
			<canvas id="canvas2"></canvas>
		</div>
		<script>
			const container = document.querySelector(".canvas-container");
			const oImageFile = document.querySelector("#oImageFile");
			const canvas = document.getElementById("canvas");
			const ctx = canvas.getContext("2d");
			const canvas2 = document.getElementById("canvas2");
			const ctx2 = canvas2.getContext("2d");
			
			const oImage = new Image();
			let initPos = [];
			const MASK_OPACITY = 0.6;
			let screenShotData = [];
			
			const init = () => {
				bindEvent();
			}
			
			function bindEvent() {
				oImageFile.addEventListener("change", handleFileChange, false);
				canvas.addEventListener("mousedown", handleCanvasMouseDown, false)
			}
			
			function handleCanvasMouseDown(e) {
				initPos = [ e.offsetX, e.offsetY ];
				canvas.addEventListener("mousemove", handleCanvasMouseMove, false);
				canvas.addEventListener("mouseup", handleCanvasMouseUp, false);
			}
			
			function handleCanvasMouseMove(e) {
				const endX = e.offsetX;
				const endY = e.offsetY;
				const [ startX, startY ] = initPos;
				const rectWidth = endX - startX;
				const rectHeight = endY - startY;
				const { width, height } = canvas;
				
				screenShotData = [ startX, startY, rectWidth, rectHeight ];
				
				ctx.clearRect(0, 0, width, height);
				drawImageMask(0, 0, width, height, MASK_OPACITY);
				drawScreenShot(width, height, rectWidth, rectHeight);
			}
			
			function handleCanvasMouseUp(e) {
				canvas.removeEventListener("mousemove", handleCanvasMouseMove);
				canvas.removeEventListener("mouseup", handleCanvasMouseUp);
				drawScreenShotImage(screenShotData);
			}
			
			function handleFileChange(e) {
				const file = e.target.files[0];
				console.log(file);
				const reader = new FileReader();
				reader.readAsDataURL(file);
				
				reader.onload = (e) => {
					const data = e.target.result;
					oImage.src = data;
					oImage.onload = function () {
						const { width, height } = this;
						generateCanvas(container, canvas, width, height);
						ctx.drawImage(oImage, 0, 0, width, height);		
						drawImageMask(0, 0, width, height, MASK_OPACITY);
					}
				}
			}
			
			function generateCanvas(container, canvas, width, height) {
				container.style.width = width + "px";
				container.style.height = height + "px";
				canvas.width = width;
				canvas.height = height;
				container.style.display = "block";
			}
			
			function drawImageMask(x, y, width, height, opacity) {
				ctx.fillStyle = `rgba(0,0,0,${opacity})`;
				ctx.fillRect(0, 0, width, height);
			}
			
			function drawScreenShot(w, h, rw, rh) {
				// 仅保留现有画布内容和新形状不重叠的部分
				ctx.globalCompositeOperation = "destination-out";
				ctx.fillStyle = "#000";
				ctx.fillRect(...initPos, rw, rh);
				// 在现有画布内容的后面绘制新的图形。
				ctx.globalCompositeOperation = "destination-over";
				ctx.drawImage(oImage, 0, 0, w, h, 0, 0, w, h);
			}
			
			function drawScreenShotImage(screenShotData) {
				const data = ctx.getImageData(...screenShotData);
				generateCanvas(canvas2, ctx2, screenShotData[2], screenShotData[3]);
				ctx2.clearRect(...screenShotData);
				ctx2.putImageData(data, 0, 0);
			}
			
			init();
		</script>
	</body>
</html>